Freelemelectronic.com

Электроника без границ.

Как уже вы поняли из названия в данной работе мы создадим GPS-GSM трекер который будет отправлять полученные от GPS модуля данные в мою базу данных на удаленном сервере. В моем распоряжении следующие устройства из которых мы будем собирать наш трекер.
1.GPS модуль GY-NEO6M
2.Отладочная плата Blue pill (синяя таблетка) c STM32F103
3.GSM/GPRS SIM800L Module
Mодуль GY-NEO6M я подключил к микроконтроллеру к пинам USART1, модуль может питаться напряжением 2.7V~5.0V с током потребления 45mA, регулятор RT9193-33 расположенный на плате Blue pill выдерживает максимальный ток до 300мА из которых 150мА максимально может сьесть сам контроллер STM32F103. Здесь с питанием все впорядке регулятор RT9193-33 полностью покрывает потребности обоих потребителей. Питание на регулятор платы Blue pill подается через USB разьем от любой телефонной зарядки. Теперь о погогворим о питании SIM800L , модуль очень придирчив к качеству питания, производитель рекомендует запитывать его от 3,7V литий-ионных аккамуляторов напрямую, напряжение питания модуля лежит в пределах 3,4-4,4V. ток модуля может достигать 2А. Подходящей батареи у меня не нешлось как и регулятора выдающего необходимое напряжение, за то с предыдущих проектов остались регуляторы AMS1117 на 3,3V, подобрав необходимые резисторы делителя в управлении стабилизатором, добавил на вход и выход регулятора емкости по 10uF и 100uF подключил его к USART3 Blue pill подал питание на SIM800L. При сопротивлениях в делителе 300ohm и 60ohm выходное напряжение составило около 4V. Общая схема подключения показана ниже.

Даташит на регулятор AMS1117 говорит что выходной ток должен быть в пределах 10mA<=IOUT<=1A практика запитывания SIM800L через AMS1117 показала что этот вариант жизнеспособен регулятор испытывает нагрев где то около 40℃ при максимально возможном to 125℃, SIM800L работает стабильно не сбрасывается.

Изначально программа трекера была написана без использования RTOS и показалась мне какой то скучной по этому я решил поэкспериментировать прикрутив операционную систему. Подключив RTOS в CUBE MX, тамже я создал две задачи с именами GPS и SIM800l, первая задача получает данные от GPS модуля GY-NEO6M, ищет в них RMC-строку с начинающеся с $GPRMC затем из данной строки извлекаются данные широты и долготы. Вторая задача SIM800l занимается отправкой данных в удаленную базу данных SQL посредством GET запроса с параметрами.

Настройка FREERTOS в CUBE MX.

Работа программы начинается с задачи с наивысшим приоритетом defaultTask, в этой задаче производится запрос к модулю SIM800l и получение от него текущей даты и времени. Полученаые данные записываются в структуру затем происходит установка таймера RTC микроконтроллера STM32F103.
После того как defaultTask попадает в режим WAIT запускается задача GPS которая навсегда отправляет defaultTask в состояние SUSPEND т.к. все необходимое она сделала и больше не нужна. Задача GPS это следующая по приоритету задача, получив и обработав данные из RMC-строки она отправляет данные в задачу SIM800l используя созданную в CUBE MX очередь send_date. У меня очередь состоит из 1 элемента типа массив typedef char AMessage[22] который определен вначале в CUBE MX затем в KEIL в Private typedef файла main.c. Когда задача GPS положит данные в очередь она переходит в режим WAIT, после чего запускается задача SIM800l которая отправляет задачу GPS в SUSPEND получает дату и время от RTC считывает данные из очереди, формирует строку POST запроса с двумя переменными, отправляет их в базу данных на удаленном сервере, по завершению отправки команда vTaskResume выводит задачу GPS из спячки и т.к. приоритет задачи GPS выше диспетчер переключается на ее исполнение.

Устройство в сборе.

Еще очень советую подключить ножку SWO асинхронной трасировки к отладчику, у меня отладка происходит через ST-LINK расположенный на плате F4DISCOVERY. Как настроить трасировку в KEIL показано здесь. После чего вы сможете выводить данные используя форматный вывод функции " printf " в самом Кейле или используя " STM32 ST-LINK Utility " картинка ниже.

STM32 ST-LINK Utility.

На рисунке выше показаны отладочные сообщения трасировщика "Message NOT delivered, FOULT!" и "foult_countner" эти сообщения приходят при получении ответа от сервера при неудачном приеме данных. При удачном приеме запроса сервер посылает ответ "+HTTPACTION: 0,200". Счетчик ошибок "foult_countner" суммирует ощибки и после превышения определенного порога сбрасывает модуль SIM800L, подтягивая пин Reset модуля SIM800L к земле на 50 мс. Затем вновь происходит установка даты и времени, программа возобновляет свою работу.

Отдельно хотелось остановиться на такой неприятной вещи как " HardFault_Handler ", данное прерывание вызывалось в моей программе не периодично и отследить причину его появления оказалось довольно сложно. Перед наступлении данного прерывания регистры ядра контроллера складываются в стек, а значит нужно прочитать данные из этого стека и определить из какого места программы происходит прерывание. Для этих целей на одном из иностранных сайтов был скачан следующий код. Код вызывается из прерывания " HardFault_Handler ".

Код моего обработчика из файла "my_asm.c".

__asm void my_HardFault_Handler(void)
{
  MOVS r0, #4
  MOV r1, LR
  TST r0, r1
  BEQ stacking_used_MSP
  MRS R0, PSP ; //first parameter - stacking was using PSP
  B get_LR_and_branch
stacking_used_MSP
  MRS R0, MSP ; //first parameter - stacking was using MSP
get_LR_and_branch
  MOV R1, LR ; //second parameter is LR current value
  LDR R2,=__cpp(hard_fault_handler_c)
  BX R2
}

void hard_fault_handler_c(unsigned int * hardfault_args)
{
unsigned int stacked_r0;
unsigned int stacked_r1;
unsigned int stacked_r2;
unsigned int stacked_r3;
unsigned int stacked_r12;
unsigned int stacked_lr;
unsigned int stacked_pc;
unsigned int stacked_psr;

stacked_r0 = ((unsigned long) hardfault_args[0]);
stacked_r1 = ((unsigned long) hardfault_args[1]);
stacked_r2 = ((unsigned long) hardfault_args[2]);
stacked_r3 = ((unsigned long) hardfault_args[3]);
stacked_r12 = ((unsigned long) hardfault_args[4]);
stacked_lr = ((unsigned long) hardfault_args[5]);
stacked_pc = ((unsigned long) hardfault_args[6]);
stacked_psr = ((unsigned long) hardfault_args[7]);

printf("[Hard fault handler]\n");
printf("R0 = %x\n", stacked_r0);
printf("R1 = %x\n", stacked_r1);
printf("R2 = %x\n", stacked_r2);
printf("R3 = %x\n", stacked_r3);
printf("R12 = %x\n", stacked_r12);
printf("LR = %x\n", stacked_lr);
printf("PC = %x\n", stacked_pc);
printf("PSR = %x\n", stacked_psr);
printf("BFAR = %x\n", (*((volatile unsigned long *)(0xE000ED38))));
printf("CFSR = %x\n", (*((volatile unsigned long *)(0xE000ED28))));
printf("HFSR = %x\n", (*((volatile unsigned long *)(0xE000ED2C))));
printf("DFSR = %x\n", (*((volatile unsigned long *)(0xE000ED30))));
printf("AFSR = %x\n", (*((volatile unsigned long *)(0xE000ED3C))));
return;
}

На нижнем рисунке показан ответ моего обработчика, причина ошибки попытка загрузить в регистр R2 значение находящееся по адресу 0xFFFFFF00+0x04, данный адрес (исходя из даташита) зарезервирован для каких то внутренних нужд контроллера. У меня данная ошибка происходила когда, по каким то причинам GPS модуль присылал невалидную строку контроллеру и после парсинга кoманда "memcpy" пыталась произвести копирование из недоступного адреса. Ошибка решена коррекцией прораммы.

Ответ обработчика " HardFault_Handler " .

Отправка данных на удаленный сервер присходит посредствам GET запроса с параметрами из подпрограммы " uint8_t send_message(char* gps_massage) " файла "my_function.c" код запроса приведен ниже.

UART_Printf("AT+HTTPPARA=\"URL\",\"freelimelectronic.com/php/sim800l.php?coord=%s&datetime=%s\"\r"\ ,gps_massage, get_RTC_str());

Ниже приведен код содежащийся на странице к которой обращается наш GET запрос.

<?php 
include ('include/connect_bd.php');

$coord = $_REQUEST['coord']; //получаем значение посланной переменной
$datetime = $_REQUEST['datetime']; //получаем значение посланной переменной

Connect_BD();//подключаемся к базе данных
$sql = "SELECT MAX(`id`) FROM `my_table` ";
$temp=mysql_result(mysql_query($sql) ,0);
//если записей больше 30 вызываем хранимую процедуру соторая очищает таблицу
if(30<=$temp){mysql_query('CALL `clear`()') ;}

$strSQL="INSERT INTO `my_table`(`datetime`, `coord`) VALUES ( '$datetime','$coord')";
mysql_query($strSQL) or die(mysql_error());

DisConnect_BD();//отключаемся от базы данных
?>

Отображение базы данных в программе " DreamWeaver " .

На рисунке отображена таблица " my_table " из базы данных "bd" содержащая данные времени и координаты полученные от моего устройства, а также структура самой таблицы . База данных находится на удаленном сервере и открыта в программе Phpmyadmin.

" Phpmyadmin " .

На следуещей странице бедет рассмотрен процесс редактирования файла "KML" для того чтобы мы могли просмотреть наш трек используя сайт "https://www.google.com/map".

Начиная с данного проекта исходники и другие файлы проекта будут выкладываться в моей ветке на сайте" github.com " ссылка на исходники данного проекта под логотипом.

You can contact the developers of the project freelemelectronic.com by e-mail:
freelimelectronic@gmail.com.